package org.hackystat.sdsa.analyzer.model.activity;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.logging.Logger;

import javax.xml.datatype.XMLGregorianCalendar;

import jess.Fact;
import jess.JessException;
import jess.Rete;

import org.hackystat.sdsa.service.resource.devstream.jaxb.ActivityTO;
import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorData;

/**
 * Define a base class that should be sub-classed by other activity classes.
 * 
 * @author hongbing
 */
public abstract class Activity implements Assertable {
  /** Logger. */
  protected Logger logger;
  /** URI of this activity. */
  private String resourceUri;
  /** When this activity occurs. */
  private XMLGregorianCalendar timestamp;
  /** Activity type. */
  private String type;
  
  /**
   * Empty constructor. 
   */
  public Activity() {
    super();
  }
  
  /**
   * Gets the time when this activity occurred.
   * 
   * @return Activity timestamp.
   */
  public XMLGregorianCalendar getTimestamp() {
    return this.timestamp;
  }
  
  /**
   * Sets the activity type. 
   * 
   * @param type Activity type. 
   */
  protected void setType(String type) {
    this.type = type;  
  }
  
  /**
   * Returns this activity type.
   * 
   * @return Activity type.
   */
  public String getType() {
    return type;  
  }
  
  /**
   * Basic development activity that
   * 
   * @param sensorData Sensor data.
   * @param logger Service logger.
   */
  public Activity(SensorData sensorData, Logger logger) {
    this.logger = logger;
    this.timestamp = sensorData.getTimestamp();
    this.resourceUri = sensorData.getResource();
  }
  
  /**
   * Gets the URI resource of this activity.
   * 
   * @return Uri string.
   */
  public String getResourceUri() {
    return this.resourceUri;
  }
  
  /**
   * Gets the file of the resource URI.
   * 
   * @param resource An URI resource.
   * @return File of the resource.
   */
  protected String extractFileName(String resource) {
    if (resource == null) {
      return "";
    }
    
    try {
      URI uri = new URI(resource);
      if (!"file".equals(uri.getScheme())) {
        logger.warning(resource + " is not a file resource.");
        return "";
      }

      String path = uri.getPath();
      File file = new File(path);
      return file.getName();
    }
    catch (URISyntaxException e) {
      logger.warning(e.getMessage());
      return "";
    }
  }
  
  /**
   * Gets the file part of the resource.
   * 
   * @return File name.
   */
  public String getResourceFile() {
    return this.extractFileName(this.resourceUri);
  }
  
  /** Get the representation of this activity. 
   * 
   * @return String representation of this activity.
   */
  public abstract String getRepresentation();
  
  /**
   * String representation of this activity.
   * 
   * @return Activity string.
   */
  @Override public String toString() {
    StringBuffer buf = new StringBuffer();
    
    buf.append(this.timestamp);
    buf.append(' ').append(this.extractFileName(this.resourceUri)).append(' ');
    buf.append(this.getType());
    
    return buf.toString();
  }
  
  /**
   * Converts this activity into a Transfer Object (ActivityTO).
   * 
   * @return Transfer object of this activity.
   */
  public ActivityTO convert() {
    ActivityTO activityTO = new ActivityTO();
    activityTO.setTime(this.timestamp);
    activityTO.setFile(this.extractFileName(this.resourceUri));
    activityTO.setType(this.type);
    activityTO.setData(this.getRepresentation());
    
    return activityTO;
  }
  
  /**
   * Updates the time when this activity occurs.
   * 
   * @param timestamp Timestamp.
   */
  public void setTimeStamp(XMLGregorianCalendar timestamp) {
    this.timestamp = timestamp;
  }
  
  /**
   * Updates the resource URI that is associated with this activity.
   * 
   * @param resourceUri Resource URI.
   */
  public void setResourceUri(String resourceUri) {
    this.resourceUri = resourceUri;
  }
  
  /**
   * Asserts this activity into the Jess's working memory.
   * 
   * @param index Index of this activity.
   * @param engine The rule engine.
   * @return The asserted activity fact.
   * @throws JessException If error occurs.
   */
  public abstract Fact assertActivity(int index, Rete engine) throws JessException;

  /**
   * Convert this activity to a transfer object that can be sent back to client,
   * 
   * @return Transfer Object of the Activity.
   */
  public ActivityTO toTransferObject() {
    ActivityTO activityTO = new ActivityTO();
    activityTO.setType(this.type);
    activityTO.setTime(this.timestamp);
    activityTO.setFile(this.extractFileName(this.resourceUri));
    activityTO.setData(this.getRepresentation());

    return activityTO;
  }
}